<template>
  <div :style="{ minHeight: '700px' }">
    <div
      :style="{
        textAlign: 'center',
        marginTop: '15px',
        marginBottom: '15px'
      }"
    >
      <a-input-group compact>
        <a-select
          v-model:value="searchType"
          @change="handleSearchTypeChange"
          size="large"
          :style="{ width: '120px', borderRadius: '20px 0px 0px 20px' }"
        >
          <a-select-option value="1">文本搜索</a-select-option>
          <a-select-option value="2">标签搜索</a-select-option>
        </a-select>

        <a-input
          v-model:value="searchTextValue"
          v-if="searchType === '1'"
          placeholder=" 请输入照片描述性文字"
          size="large"
          :style="{
            width: '55%',
            minWidth: '600px',
            margin: '0 auto',
            textAlign: 'left'
          }"
        />

        <a-select
          v-model:value="searchTagValue"
          size="large"
          v-else
          :style="{
            width: '55%',
            minWidth: '600px',
            margin: '0 auto',
            textAlign: 'left'
          }"
        >
          <a-select-option
            :value="tag.tagId"
            v-for="(tag, index) in allTagList"
            :key="index"
            >{{ tag.tagName }}</a-select-option
          >
        </a-select>

        <a-button
          size="large"
          type="primary"
          :style="{ borderRadius: '0px 20px 20px 0px', width: '60px' }"
          @click="search"
          ><SearchOutlined />
        </a-button>
      </a-input-group>
    </div>

    <a-empty
      v-if="!list.length && !loading"
      description="暂无照片～"
      :style="{ marginTop: '100px' }"
    />
    <div :style="{ position: 'relative', minHeight: '700px' }">
      <div class="container" id="container">
        <a-image-preview-group>
          <div
            class="column"
            v-for="(column, index) in waterfallColumn"
            :key="`${index}${Math.random()} `"
          >
            <div
              class="item"
              v-for="(item, i) in column.columnArr"
              :key="i"
              :style="{ height: item.height + 65 + 'px', top: item.top + 'px' }"
            >
              <PictureCard
                :picid="item.picId"
                :albumid="item.albumId"
                :albumName="item.albumName"
                :filesize="item.fileSize"
                :tags="item.tags"
                :filelink="item.fileLink"
                :filename="item.fileName"
                :tagList="allTagList"
              />
            </div>
          </div>
        </a-image-preview-group>
      </div>
      <br />
      <div
        :style="{ margin: '0 auto', marginBottom: '20px', textAlign: 'center' }"
      >
        <a-spin :spinning="loading" tip="加载中..."></a-spin>
      </div>
    </div>
  </div>
</template>
<script lang="ts">
import { defineComponent, onMounted, reactive, ref } from 'vue';
import {
  getPictureList,
  searchByTagList,
  searchByTextList
} from '@/apis/picture';
import { getTagList } from '@/apis/tag';
import PictureCard from './components/PictureCard.vue';
import { SearchOutlined } from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';

interface PictureType {
  status: number;
  picId: number;
  albumId: number;
  albumName: string;
  hashCode: number;
  fileName: string;
  fileLink: string;
  fileSize: number;
  createTime: string;
  updateTime: string;
  tags: string;
  width: number;
  height: number;
  top?: number;
}

interface PaginationType {
  current: number;
  pageSize: number;
  total: number;
}

interface TagType {
  createTime: string;
  tagId: number;
  tagName: string;
  updateTime: string;
  userId: number;
}

interface TopHeightType {
  top: number;
  height: number;
}

interface ImgColumnType {
  columnArr: Array<PictureType>;
}

export default defineComponent({
  components: {
    PictureCard,
    SearchOutlined
  },
  setup() {
    const searchType = ref<string>('1');

    const searchTextValue = ref<string>('');

    const searchTagValue = ref<number>(0);

    const loading = ref<boolean>(false);

    const allTagList = ref<Array<TagType>>([]);
    getTagList().then((res) => {
      allTagList.value = res.data.list;
    });

    // 分页配置，记载每次瀑布流下拉要获取的图片
    const pagination = reactive<PaginationType>({
      current: 1,
      pageSize: 10,
      total: 0
    });

    // 初始化照片列表
    const list: Array<PictureType> = reactive([]);

    // 初始化瀑布流每列
    const waterfallColumn: Array<ImgColumnType> = reactive([]);

    // 图片宽度
    const imgWidth: number = 250;

    // 最小高度列
    const minHeightIndexArr: Array<number> = reactive([]);

    // 获取arr中的最小高度
    const getMinHeight = (arr: Array<TopHeightType>) => {
      const a = [];
      for (let i = 0; i < arr.length; i++) {
        a.push(arr[i].height + arr[i].top);
      }
      return Math.min.apply(null, a);
    };

    // 获取最小高度的图片index
    const getMinIndex = (val: number) => {
      for (let i = 0; i < waterfallColumn.length; i++) {
        const height =
          waterfallColumn[i].columnArr[waterfallColumn[i].columnArr.length - 1]
            .height;
        const top =
          waterfallColumn[i].columnArr[waterfallColumn[i].columnArr.length - 1]
            .top;
        if (
          typeof height === 'number' &&
          typeof top === 'number' &&
          height + top === val
        ) {
          minHeightIndexArr.push(i);
        }
      }
    };

    const init = () => {

      // 初始化瀑布流的数组
      waterfallColumn.splice(0, waterfallColumn.length);

      // 获取图片的长度
      const contentLen = list.length;

      // 根据可视区域的宽度判断需要几列
      const cWidth = document.getElementById('container')!.clientWidth;

      // document.documentElement.clientWidth || document.body.clientWidth;

      // 假设图片宽度为250px
      const cLen = Math.floor((cWidth - 50) / imgWidth);

      // 初始化每一列的第一行元素
      for (let i = 0; i < cLen; i++) {
        if (i < list.length) {
          const {
            picId,
            status,
            albumId,
            albumName,
            hashCode,
            fileName,
            fileLink,
            fileSize,
            height,
            width,
            top,
            tags,
            createTime,
            updateTime
          } = list[i];
          const imgData: PictureType = {
            picId,
            status,
            albumId,
            albumName,
            hashCode,
            fileName,
            fileLink,
            fileSize,
            height,
            width,
            top,
            tags,
            createTime,
            updateTime
          };
          imgData.height = (imgWidth / imgData.width) * imgData.height;
          imgData.top = 0; // 预设距离顶部值为0
          waterfallColumn.push({ columnArr: [imgData] });
        } else {
          waterfallColumn.push({ columnArr: [] });
        }
      }

      // 对剩余元素的判断，应该放到哪一列
      for (let index = cLen; index < contentLen; index++) {
        minHeightIndexArr.splice(0, minHeightIndexArr.length);
        const arr: Array<TopHeightType> = []; // 找到高度最小的一列，可能有多个
        let minHeight = 0; // 高度最小的一列的高度
        let pushIndex = 0; // 高度最小的一列所在位置的索引
        for (let i = 0; i < waterfallColumn.length; i++) {
          const height =
            waterfallColumn[i].columnArr[
              waterfallColumn[i].columnArr.length - 1
            ].height;
          const top =
            waterfallColumn[i].columnArr[
              waterfallColumn[i].columnArr.length - 1
            ].top;
          if (typeof height === 'number' && typeof top === 'number') {
            arr.push({ height, top });
          }
        }
        minHeight = getMinHeight(arr);
        getMinIndex(minHeight);

        if (minHeightIndexArr.length > 0) {
          pushIndex = Math.min.apply(null, minHeightIndexArr); // 出现高度一样的，去索引最小的
        }
        const {
          picId,
          status,
          albumId,
          albumName,
          hashCode,
          fileName,
          fileLink,
          fileSize,
          height,
          width,
          tags,
          top,
          createTime,
          updateTime
        } = list[index];
        const imgData: PictureType = {
          picId,
          status,
          albumId,
          albumName,
          hashCode,
          fileName,
          fileLink,
          fileSize,
          height,
          width,
          top,
          tags,
          createTime,
          updateTime
        };
        imgData.height = (imgWidth / imgData.width) * imgData.height;
        imgData.top = minHeight + 20; // 预设距离顶部值为0
        waterfallColumn[pushIndex].columnArr.push(imgData);
      }
    };

    const refresh = () => {
      if (list.length !== 0 && list.length === pagination.total) {
        message.warn('已经没有图片啦～');
      } else {
        loading.value = true;
        getPictureList(pagination.current, pagination.pageSize).then((res) => {
          list.push.apply(list, res.data.list);
          pagination.total = res.data.total;
          pagination.current++;
          loading.value = false;
          init();
        });
      }
    };

    const searchByTag = () => {
      if (list.length !== 0 && list.length === pagination.total) {
        message.warn('已经没有图片啦～');
      } else {
        loading.value = true;
        searchByTagList(
          searchTagValue.value,
          pagination.current,
          pagination.pageSize
        ).then((res) => {
          list.push.apply(list, res.data.list);
          pagination.total = res.data.total;
          pagination.current++;
          loading.value = false;
          init();
        });
      }
    };

    const searchByText = () => {
      if (list.length !== 0) {
        message.warn('已经没有图片啦～');
      } else {
        loading.value = true;
        searchByTextList(searchTextValue.value).then((res) => {
          list.push.apply(list, res.data.list);
          pagination.total = res.data.total;
          pagination.current++;
          loading.value = false;
          console.log(list);
          init();
        });
      }
    };

    const handleSearchTypeChange = (e: any) => {
      finalSearchType.value = e;
      searchTagValue.value = allTagList.value[0].tagId;
      searchTextValue.value = '';
    };

    const finalSearchType = ref('1');

    const search = () => {
      pagination.current = 1;
      pagination.pageSize = 10;
      pagination.total = 0;

      if (searchTextValue.value === '' && finalSearchType.value === '1') {
        finalSearchType.value = '0';
      }

      list.splice(0, list.length);
      init();

      switch (finalSearchType.value) {
        case '0':
          refresh();
          break;
        case '1':
          searchByText();
          break;
        case '2':
          searchByTag();
          break;
        default:
      }
    };

    // const debounce = (fn: any) => {
    //   let t: any = null; // 往这里传e
    //   return (e: any) => {
    //     if (t) {
    //       clearTimeout(t);
    //     }
    //     t = setTimeout(() => {

    //       // 再带给fn
    //       fn(e);
    //     }, 1000);
    //   };
    // };

    onMounted(() => {
      refresh();
      window.onresize = () => {
        init();
      };

      document.onscroll = (e: any) => {

        // 获取滚动的距离
        const scrollTop = document.documentElement.scrollTop;

        // 获取滚动的高度（获取整个html的高度）
        const scrollHeight = document.documentElement.scrollHeight;

        // 获取屏幕(浏览器)高度
        const clienHeight = document.documentElement.clientHeight;
        if (searchTextValue.value === '' && finalSearchType.value === '1') {
          finalSearchType.value = '0';
        }

        // console.log(Math.abs(scrollTop + clienHeight - scrollHeight));

        // 滚动的距离 + 屏幕高度 - 内容高度 >= 0 表示滚动到底部了      (下拉加载判断条件)
        if (
          Math.abs(scrollTop + clienHeight - scrollHeight) === 0.5 &&
          finalSearchType.value === '0'
        ) {
          refresh();
        }
      };
    });

    return {
      searchType,
      searchTagValue,
      searchTextValue,
      list,
      init,
      waterfallColumn,
      pagination,
      search,
      allTagList,
      handleSearchTypeChange,
      loading
    };
  }

  //   debounce(func, timeout) {
  //     let timer;
  //     return function() {
  //       if (timer) {

  //         // 如果在timeout秒调用 清空定时器
  //         clearTimeout(timer);
  //       }

  //       // 每次调用都指定timeout后再执行
  //       timer = setTimeout(() => {
  //         timer = null;
  //         func();
  //       }, timeout);
  //     };
  //   },
});
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
div,
p {
  margin: 0;
  padding: 0;
}
.container {
  margin: 0 auto;
  padding-bottom: 20px;
  display: flex;
  // justify-content: space-around;
  justify-content: center;
  /* background: pink; */
  transition: all 0.5s ease-in-out;
}
.item {
  width: 250px;
  color: #000;
  // margin-top: 20px;
  margin: 10px 8px 10px 8px;
  display: flex;
  justify-content: center;
  align-items: center;
  transition: all 0.5s ease-in-out;
}
.loading {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.pic-button {
  display: inline-block;
  margin-left: 20px;
}
</style>
